<?php
abstract Class Util{

	public static function cast($object, $class){
		$log = new Logger("CAST", _LOGPATH_);
		$log->setLogLevel(Logger::DEBUG);
		$log->debug("casting ".get_class($object)." to $class");

		$reflectionClass = new ReflectionClass($class);

		if ( ! $reflectionClass->IsInstantiable() )	{
			$log->error("$class is not instantiable!");
		}

		if ($object instanceof $class){
			$log->info("casting from $object to class $class was unnecessary");
			return $object;
		}

		$tmpObject = $reflectionClass->newInstance();

		$properties = Array();
		foreach ( $reflectionClass->getProperties() as $property ){
			$properties[ $property->getName() ] = $property;
		}

		$parentClass = $reflectionClass;
		while ($parentClass = $parentClass->getParentClass()){
			foreach ($parentClass->getProperties() as $property){
				$properties[ $property->getName() ] = $property;
			}
		}

		$vars = get_object_vars( $object );
		foreach ( $vars as $varName => $varValue ){
			if ( array_key_exists( $varName, $properties ) ){
				$prop = $properties[ $varName ];
				if (!$prop->isPublic()){
					$prop->setAccessible(true);
				}
				$prop->setValue( $tmpObject, $varValue );
			}
		}
		return $tmpObject;
	}

	public static function getStatusCodeMessage($status){
		$log = new Logger("STATUSCODE", _LOGPATH_);
		$log->setLogLevel(Logger::VERBOSE);
		$log->verbose("getting message for status $status" );
		$codes = Array(
		100 => 'Continue',
		101 => 'Switching Protocols',
		200 => 'OK',
		201 => 'Created',
		202 => 'Accepted',
		203 => 'Non-Authoritative Information',
		204 => 'No Content',
		205 => 'Reset Content',
		206 => 'Partial Content',
		300 => 'Multiple Choices',
		301 => 'Moved Permanently',
		302 => 'Found',
		303 => 'See Other',
		304 => 'Not Modified',
		305 => 'Use Proxy',
		306 => '(Unused)',
		307 => 'Temporary Redirect',
		400 => 'Bad Request',
		401 => 'Unauthorized',
		402 => 'Payment Required',
		403 => 'Forbidden',
		404 => 'Not Found',
		405 => 'Method Not Allowed',
		406 => 'Not Acceptable',
		407 => 'Proxy Authentication Required',
		408 => 'Request Timeout',
		409 => 'Conflict',
		410 => 'Gone',
		411 => 'Length Required',
		412 => 'Precondition Failed',
		413 => 'Request Entity Too Large',
		414 => 'Request-URI Too Long',
		415 => 'Unsupported Media Type',
		416 => 'Requested Range Not Satisfiable',
		417 => 'Expectation Failed',
		500 => 'Internal Server Error',
		501 => 'Not Implemented',
		502 => 'Bad Gateway',
		503 => 'Service Unavailable',
		504 => 'Gateway Timeout',
		505 => 'HTTP Version Not Supported'
		);
		if(isset($codes[$status])){
			$statusMessage = $codes[$status];
		}else{
			$statusMessage = "unknown status";
			$log->warning("Responding unknown status message. Status is: $status");
		}
		return $statusMessage;
	}

	public static function dump($object){
		echo '<pre>' . print_r($object, true) . '</pre>';
	}

	public static function getUniqueKey($bytes = 32, $prefix=""){
		$characters = 'abcdefghijklmnopqrstuvwxyz0123456789';
		$string ="";
		for ($i = 0; $i < $bytes-13; $i++) {
			$string .= $characters[rand(0, strlen($characters) - 1)];
		}
		$string .= uniqid($prefix);
		return $string;
	}

	public static function gmstrtotime($timeString) {
		return(strtotime($timeString . " UTC"));
	}

	public static function parseUserAgent($useragent = ""){



		if($useragent == ""){
			$useragent = $_SERVER['HTTP_USER_AGENT'];
		}

		if($useragent=="-\n"||$useragent=="-"){
			return (object) array(
					        'userAgent' => 'unknown',
							'platform'  => 'unknown',
					        'browser'   => 'unknown',
					        'version'   => 'unknown',
			);
		}

		if(preg_match('/Windows 95/i',$useragent) || preg_match('/Win95/',$useragent)) {
			$platform = "Windows 95";
		} elseif (preg_match('/Windows NT 5.0/i',$useragent) || preg_match('/Windows 2000/i', $useragent)) {
			$platform = "Windows 2000";
		} elseif (preg_match('/Win 9x 4.90/i',$useragent) || preg_match('/Windows ME/i', $useragent)) {
			$platform = "Windows ME";
		} elseif (preg_match('/Windows.98/i',$useragent) || preg_match('/Win98/i', $useragent)) {
			$platform = "Windows 98";
		} elseif (preg_match('/Windows NT 6.0/i',$useragent)) {
			$platform = "Windows Vista";
		} elseif (preg_match('/Windows NT 6.1/i',$useragent)) {
			$platform = "Windows 7";
		} elseif (preg_match('/Windows NT 5.1/i',$useragent)) {
			$platform = "Windows XP";
		} elseif (preg_match('/Windows NT 5.2/i',$useragent) && preg_match('/Win64/i',$useragent)) {
			$platform = "Windows XP 64 bit";
		} elseif (preg_match('/Windows NT 5.2/i',$useragent)){
			$platform = "Windows Server 2003";
		} elseif (preg_match('/Mac_PowerPC/i',$useragent)) {
			$platform = "Mac OS";
		} elseif (preg_match('/Windows Phone/i',$useragent)) {
			$platform = "windows phone7";
		} elseif (preg_match('/Windows NT 4.0/i',$useragent) || preg_match('/WinNT4.0/i',$useragent)) {
			$platform = "Windows NT 4.0";
		} elseif (preg_match('/Windows NT/i',$useragent) || preg_match('/WinNT/i',$useragent)) {
			$platform = "Windows NT";
		} elseif (preg_match('/Windows CE/i',$useragent)) {
			$platform = "Windows CE";
		} elseif (preg_match('/Android/i',$useragent)) {
			$platform = "Android";
		} elseif (preg_match('/iPod/i',$useragent)) {
			$platform = "iPod";
		} elseif (preg_match('/iPad/i',$useragent)) {
			$platform = "iPad";
		} elseif (preg_match('/iPhone/i',$useragent)) {
			$platform = "iPhone";
		} elseif(preg_match('/Opera Mini/i',$useragent)){
			$platform = 'mobile';
		}elseif (preg_match('/Symbian/i',$useragent) || preg_match('/SymbOS/i',$useragent)) {
			$platform = "Symbian OS";
		} elseif (preg_match('/PalmOS/i',$useragent)) {
			$platform = "Palm OS";
		}elseif(preg_match('/iPhone OS/i',$useragent)){
			$platform = 'iPhone';
		}elseif(preg_match('/iPad/i',$useragent)){
			$platform = 'iPad';
		}elseif (preg_match('/Touch/i',$useragent)) {
			$platform = "Touchw";
		} elseif (preg_match('/QtEmbedded/i',$useragent)) {
			$platform = "Qtopia";
		} elseif (preg_match('/Ubuntu/i',$useragent)) {
			$platform = "Ubuntu Linux";
		} elseif (preg_match('/Gentoo/i',$useragent)) {
			$platform = "Gentoo Linux";
		} elseif (preg_match('/Fedora/i',$useragent)) {
			$platform = "Fedora Linux";
		} elseif (preg_match('/FreeBSD/i',$useragent)) {
			$platform = "FreeBSD";
		} elseif (preg_match('/NetBSD/i',$useragent)) {
			$platform = "NetBSD";
		} elseif (preg_match('/OpenBSD/i',$useragent)) {
			$platform = "OpenBSD";
		} elseif (preg_match('/SunOS/i',$useragent)) {
			$platform = "SunOS";
		} elseif (preg_match('/Linux/i',$useragent)) {
			$platform = "Linux";
		} elseif (preg_match('/Mac OS X/i',$useragent)) {
			$platform = "Mac OS X";
		} elseif (preg_match('/Macintosh/i',$useragent)) {
			$platform = "Mac OS";
		} elseif (preg_match('/Unix/i',$useragent)) {
			$platform = "Unix";
		} elseif (preg_match('#Nokia([a-zA-Z0-9.]+)#i',$useragent,$matches)) {
			$platform = "Nokia".$matches[1];
		} elseif (preg_match('/Mac OS X/i',$useragent)) {
			$platform = "Mac OS X";
		}else{
			$platform = 'other';
		}

		if(preg_match('/MSIE/i',$useragent) && !preg_match('/Opera/i',$useragent)){
			$bname = 'Internet Explorer';
			$ub = "MSIE";
		}elseif(preg_match('/Firefox/i',$useragent)){
			$bname = 'Mozilla Firefox';
			$ub = "Firefox";
		}elseif(preg_match('/Chrome/i',$useragent)){
			$bname = 'Google Chrome';
			$ub = "Chrome";
		}elseif(preg_match('/Safari/i',$useragent)){
			$bname = 'Safari';
			$ub = "Safari";
		}elseif(preg_match('/Opera/i',$useragent)&& !preg_match('/Opera Mini/i',$useragent)&&!preg_match('/Opera Mobi/i',$useragent)){
			$bname = 'Opera';
			$ub = "Opera";
		}elseif(preg_match('/Netscape/i',$useragent)){
			$bname = 'Netscape';
			$ub = "Netscape";
		}elseif(preg_match('/PLAYSTATION/i',$useragent)){
			$bname = 'Playstation';
			$ub = "Playstation";
		}elseif(preg_match('/Java/i',$useragent)){
			//Java
			$bname = 'Java';
			$ub = "Java";
			$platform = 'Java';
			//validator
		}elseif(preg_match('/W3C_Validator/i',$useragent)){
			$bname = 'W3C Validator';
			$ub = "W3C_Validator";
			$platform = 'Validator';
			// mobile
		}elseif(preg_match('/W3C_CSS_Validator/i',$useragent)){
			$bname = 'W3C CSS Validator';
			$ub = "W3C_CSS_Validator";
			$platform = 'Validator';
			// mobile
		}elseif(preg_match('/Opera Mobi/i',$useragent)){
			$bname = 'Opera Mobi';
			$ub = "Opera Mobi";
		}elseif(preg_match('/Opera Mini/i',$useragent)){
			$bname = 'Opera Mini';
			$ub = "Opera Mini";
		}elseif (preg_match('/Symbian/i',$useragent) || preg_match('/SymbOS/i',$useragent)) {
			$bname = 'Symbian OS';
			$ub = "Symbian OS";
		} elseif (preg_match('/PalmOS/i',$useragent)) {
			$bname = 'Palm OS';
			$ub = "Palm OS";
		}elseif(preg_match('/iPhone OS/i',$useragent)){
			$bname = 'Safari';
			$ub = "iPhone OS";
		}elseif(preg_match('/iPad/i',$useragent)){
			$bname = 'Apple iPad';
			$ub = "iPad";
			//robots & spiders
		}elseif(preg_match('/Baiduspider/i',$useragent)){
			$bname = 'Baiduspider';
			$ub = "Baiduspider";
			$platform = 'bot';
		}elseif(preg_match('/Googlebot/i',$useragent)){
			$bname = 'Googlebot';
			$ub = "Googlebot";
			$platform = 'bot';
		}elseif(preg_match('/TurnitinBot/i',$useragent)){
			$bname = 'TurnitinBot';
			$ub = "TurnitinBot";
			$platform = 'bot';
		}elseif(preg_match('/YandexBot/i',$useragent)){
			$bname = 'YandexBot';
			$ub = "YandexBot";
			$platform = 'bot';
		}elseif(preg_match('/BacklinkCrawler/i',$useragent)){
			$bname = 'BacklinkCrawler';
			$ub = "BacklinkCrawler";
			$platform = 'bot';
		}elseif(preg_match('/WBSearchBot/i',$useragent)){
			$bname = 'WBSearchBot';
			$ub = "WBSearchBot";
			$platform = 'bot';
		}elseif(preg_match('/123peoplebot/i',$useragent)){
			$bname = '123peoplebot';
			$ub = "123peoplebot";
			$platform = 'bot';
		}elseif(preg_match('/bingbot/i',$useragent)){
			$bname = 'bingbot';
			$ub = "bingbot";
			$platform = 'bot';
		}elseif(preg_match('/bot/i',$useragent)||preg_match('/Bot/i',$useragent)||preg_match('/crawler/i',$useragent)||preg_match('/Crawler/i',$useragent)){
			$bname = 'bot';
			$ub = "bot";
			$platform = 'bot';
		}else{
			$bname = 'other';
			$ub = "other";
		}


		$known = array('Version', $ub, 'other');
		$pattern = '#(?<browser>' . join('|', $known) .
		    ')[/ ]+(?<version>[0-9.|a-zA-Z.]*)#';
		if (!preg_match_all($pattern, $useragent, $matches)) {
			// we have no matching number just continue
		}

		$i = count($matches['browser']);
		if ($i > 1) {
			if (strripos($useragent,"Version") < strripos($useragent,$ub)){
				$version= $matches['version'][0];
			}
			else {
				$version= $matches['version'][1];
			}
		}else if ($i == 1){
			$version= $matches['version'][0];
		}else {
			$version="?";
		}

		return (object) array(
		        'userAgent' => $useragent,
				'platform'  => $platform,
		        'browser'   => $bname,
		        'version'   => $version,
		);
	}

}